﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using KJFrame.Core.Rpc.Protocol.Serializers;
using KJFrame.Core.Rpc.Protocol;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System;
using System.Linq;
using Microsoft.Extensions.DependencyModel;
using System.Reflection;

namespace KJFrame.Core.Rpc.Client
{
    /// <summary>
    /// 扩展类
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 获取RpcClient配置节点，并添加Rpc客户端
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IServiceCollection AddRpcClient(this IServiceCollection services, IConfiguration configuration)
        {
            services.TryAddSingleton<ISerializer, ProtoBufSerializer>();
            services.TryAddScoped<IRpcChannel, DefaultRpcChannel>();
            //services.TryAddScoped<IRpcServiceDiscovery, ConsulRpcServiceDiscovery>();
            services.TryAddScoped<IRpcServiceDiscovery, DefaultRpcServiceDiscovery>();

            services.Configure<RpcClientOptions>(configuration.GetSection(RpcConfigInformation.RpcClientConfigSectionName));

            return services;
        }

        /// <summary>
        /// 注册特定IRpcService服务
        /// </summary>
        /// <typeparam name="TServiceInterface"></typeparam>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddRpcClientService<TServiceInterface>(this IServiceCollection services)
    where TServiceInterface : class, IRpcService
        {
            services.AddScoped<TServiceInterface>(serviceProvider =>
            {
                var rpcChannel = serviceProvider.GetRequiredService<IRpcChannel>();

                return RpcClientFactory.Create<TServiceInterface>(rpcChannel);
            });

            return services;
        }

        private static readonly Regex _ignoreNamespaceRegex = new Regex("^System.*|^Microsoft.*|^Grpc.*|^netstandard*|^Newtonsoft.*|^Autofac.*|^KJFrame.Core.Rpc.Protocol.*", RegexOptions.IgnoreCase);

        private static List<Type> FindService()
        {
            var typeOfRpc = typeof(IRpcService);
            var rpcTypes = DependencyContext.Default.RuntimeLibraries.SelectMany(i => i.GetDefaultAssemblyNames(DependencyContext.Default).Select(z => Assembly.Load(new AssemblyName(z.Name)))).ToArray();
            List<Type> list = new List<Type>();
            foreach (var item in rpcTypes)
            {
                if (!item.IsDynamic && !_ignoreNamespaceRegex.IsMatch(item.GetName().Name))
                {
                    var items = item.GetExportedTypes();
                    if (items != null && items.Any())
                    {
                        foreach (var i in items)
                        {
                            if (i.IsInterface && typeOfRpc.IsAssignableFrom(i))
                                list.Add(i);
                        }
                    }
                }
            }
            return list;
        }

        /// <summary>
        /// 注册所有的IRpcService服务
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddRpcClientService(this IServiceCollection services)
        {
            List<Type> items = FindService();
            foreach (var item in items)
            {
                services.AddScoped(item, (provider) =>
                {
                    var rpcChannel = provider.GetRequiredService<IRpcChannel>();
                    return RpcClientFactory.Create(rpcChannel, item);
                });
            }
            return services;
        }
    }
}
